package cn.skyquant.quant4j.sdk.util.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;

/**
 * Http服务类
 * Created by harley-dog on 2016/4/23.
 */
public final class HttpUtils {

    private static final String COOKIE = "Cookie";
    private static final String REFERER = "Referer";
    private static final String UTF8 = "UTF-8";
    private static final String S1 = "=";
    private static final String S2 = ";";
    private static final String S3 = "?";
    private static final String OK = "ok";
    private static final String MESSAGE = "message";
    private static final JSONObject error = new JSONObject();
    private static final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
    private static HttpClientBuilder httpBuilder;

    static {
        error.put(OK, false);
        error.put(MESSAGE, "网络错误");
        connectionManager.setMaxTotal(20);
        connectionManager.setDefaultMaxPerRoute(5);//例如默认每路由最高50并发，具体依据业务来定
        httpBuilder = HttpClients.custom().setConnectionManager(connectionManager);
    }

    public static final JSONObject get(String uristr, Map<String, String> paramMap, Map<String, String> cookieMap, Map<String,String> headerMap) {
        CloseableHttpResponse response = null;
        CloseableHttpClient httpclient = null;
        try {
            StringBuffer url = new StringBuffer(uristr);
            List<NameValuePair> params = Lists.newArrayList();
            if (paramMap != null) {
                paramMap.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));
                String param_str = URLEncodedUtils.format(params, UTF8);
                url.append(S3).append(param_str);
            }
            URI uri = new URI(url.toString());
            HttpGet httpget = new HttpGet(uri);
            if (cookieMap != null) {
                StringBuilder sb = new StringBuilder();
                cookieMap.forEach((k, v) -> sb.append(k).append(S1).append(v).append(S2));
                httpget.setHeader(COOKIE, sb.toString());
            }
            if (headerMap != null) {
                headerMap.forEach((k,v) -> httpget.setHeader(k,v));
            }
            httpclient =  HttpClients.custom().build();
            response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
            String s = EntityUtils.toString(entity);
            JSONObject obj = JSON.parseObject(s);
            return obj;
        } catch (Exception e) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(OK,false);
            jsonObject.put(MESSAGE,e.getMessage());
            return jsonObject;
        } finally {
            try {
                if (response != null) {
                    response.close();

                }
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException e) {

            }
        }
    }

    public static final JSONArray getArray(String uristr, Map<String, String> paramMap, Map<String, String> cookieMap, Map<String,String> headerMap) {
        CloseableHttpResponse response = null;
        CloseableHttpClient httpclient = null;
        try {
            StringBuffer url = new StringBuffer(uristr);
            List<NameValuePair> params = Lists.newArrayList();
            if (paramMap != null) {
                paramMap.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));
                String param_str = URLEncodedUtils.format(params, UTF8);
                url.append(S3).append(param_str);
            }
            URI uri = new URI(url.toString());
            HttpGet httpget = new HttpGet(uri);
            if (cookieMap != null) {
                StringBuilder sb = new StringBuilder();
                cookieMap.forEach((k, v) -> sb.append(k).append(S1).append(v).append(S2));
                httpget.setHeader(COOKIE, sb.toString());
            }
            if (headerMap != null) {
                headerMap.forEach((k,v) -> httpget.setHeader(k,v));
            }
            httpclient =  HttpClients.custom().build();
            response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
            String s = EntityUtils.toString(entity);
            JSONArray obj = JSON.parseArray(s);
            return obj;
        } catch (Exception e) {
            JSONArray jsonObject = new JSONArray();
            return jsonObject;
        } finally {
            try {
                if (response != null) {
                    response.close();

                }
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException e) {

            }
        }
    }

    public static final JSONObject post(String uri, Map<String, String> paramMap, Map<String, String> cookieMap, Map<String,String> headerMap) {
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost(uri);
            List<NameValuePair> params = Lists.newArrayList();
            if (paramMap != null) {
                paramMap.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));
                httpPost.setEntity(new UrlEncodedFormEntity(params, UTF8));
            }
            if (cookieMap != null) {
                StringBuilder sb = new StringBuilder();
                cookieMap.forEach((k, v) -> sb.append(k).append(S1).append(v).append(S2));
                httpPost.setHeader(COOKIE, sb.toString());
            }
            if (headerMap != null) {
                headerMap.forEach((k,v) -> httpPost.setHeader(k,v));
//                httpPost.setHeader(REFERER, referer.trim());
            }
            httpclient =  HttpClients.custom().build();
            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String s = EntityUtils.toString(entity);
            JSONObject obj = JSON.parseObject(s);
            return obj;
        }catch (Exception e){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(OK,false);
            jsonObject.put(MESSAGE,e.getMessage());
            return  jsonObject;
        }finally {
            try {
                if (response != null) {
                    response.close();

                }
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException ex) {

            }
        }

    }

    public static final JSONObject put(String uri, Map<String, String> paramMap, Map<String, String> cookieMap, Map<String,String> headerMap){
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        try {
            HttpPut httpPut = new HttpPut(uri);
            List<NameValuePair> params = Lists.newArrayList();
            if (paramMap != null) {
                paramMap.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));
                httpPut.setEntity(new UrlEncodedFormEntity(params, UTF8));
            }
            if (cookieMap != null) {
                StringBuilder sb = new StringBuilder();
                cookieMap.forEach((k, v) -> sb.append(k).append(S1).append(v).append(S2));
                httpPut.setHeader(COOKIE, sb.toString());
            }
            if (headerMap != null) {
                headerMap.forEach((k,v) -> httpPut.setHeader(k,v));
//                httpPost.setHeader(REFERER, referer.trim());
            }
            httpclient =  HttpClients.custom().build();
            response = httpclient.execute(httpPut);
            HttpEntity entity = response.getEntity();
            String s = EntityUtils.toString(entity);
            JSONObject obj = JSON.parseObject(s);
            return obj;
        }catch (Exception e){
            return  error;
        }finally {
            try {
                if (response != null) {
                    response.close();

                }
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException ex) {

            }
        }
    }

    public static final JSONObject delete(String uri, Map<String, String> cookieMap, Map<String,String> headerMap){
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        try {
            HttpDelete httpDelete = new HttpDelete(uri);
            if (cookieMap != null) {
                StringBuilder sb = new StringBuilder();
                cookieMap.forEach((k, v) -> sb.append(k).append(S1).append(v).append(S2));
                httpDelete.setHeader(COOKIE, sb.toString());
            }

            if (headerMap != null) {
                headerMap.forEach((k,v) -> httpDelete.setHeader(k,v));
//                httpPost.setHeader(REFERER, referer.trim());
            }
            httpclient =  HttpClients.custom().build();
            response = httpclient.execute(httpDelete);
            HttpEntity entity = response.getEntity();
            String s = EntityUtils.toString(entity);
            JSONObject obj = JSON.parseObject(s);
            return obj;
        }catch (Exception e){
            return  error;
        }finally {
            try {
                if (response != null) {
                    response.close();

                }
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException ex) {

            }
        }

    }
}
